//==================================================================
//  Copyright (C) 2006  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
///
///
///
///
///
//==================================================================

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "psys.h"
#include "m5d_pntsprt.h"
#include "rendm5d_pntsprt.h"

//==================================================================
using namespace M5D;
/*
//==================================================================
#ifdef TARGET_D3D
//------------------------------------------------------------------
// Custom vertex types
//------------------------------------------------------------------
struct PARTICLE_VERTEX
{
	FLOAT3	v;
	DWORD	color;
};
#endif
*/

//==================================================================
RendM5D::PntSprt::PntSprt( M5D::PntSprt *mpntsprtp, RendDevice *rdevicep ) :
	_mpntsprtp(mpntsprtp),
	_rdevicep(rdevicep),
	_cur_buff_idx(0)
{
	_mpntsprtp->_userdatap = (void *)this;

	DispListBase	*dlistp = _mpntsprtp->GetDispList();

	for(int i=0; i < NUM_PARTICLE_BUFFERS; ++i)
	{
		_vbuffs[i] = new RendVertexBuffer( _rdevicep, dlistp->_vert_def._n_verts, dlistp->GetVertStride() );
		// needs update right from the start
		_need_update[i] = true;
	}
/*
#ifdef TARGET_D3D
	D3DDevice	*d3ddevp = _rdevicep->GetD3DDevice();
	HRESULT		hr;

	DispListBase	*dlistp = _mpntsprtp->GetDispList();

	for(int i=0; i < NUM_PARTICLE_BUFFERS; ++i)
	{
		hr = d3ddevp->CreateVertexBuffer( (dlistp->_verts_n+1)*dlistp->_vert_stride,
									D3DUSAGE_WRITEONLY, 0L,
									D3DPOOL_DEFAULT, &_xbox_pPointSpritesVBs[i], NULL );

		if ERR_ERROR( hr )
		{
			throw "CreateVertexBuffer failed";
			return;
		}

		// needs update right from the start
		_need_update[i] = true;
	}
#endif
*/
}

//==================================================================
RendM5D::PntSprt::~PntSprt()
{
}

//==================================================================
void RendM5D::PntSprt::updateGeometry( int buff_idx )
{
	PASSERT( _rdevicep->IsRendering() == false );

	_vbuffs[buff_idx]->UploadData( _mpntsprtp->GetDispList()->_vert_def.GetVertPtr(0,VType::POS),
									0,
									_mpntsprtp->GetActiveVerts() );
/*
#ifdef TARGET_D3D
	D3DVertexBuffer	*vbuffp = _xbox_pPointSpritesVBs[ buff_idx ];

	int n = _mpntsprtp->GetActiveVerts();

	PARTICLE_VERTEX	*part_vertsp;

	vbuffp->Lock( 0, 0, (VOID**)&part_vertsp, NULL );
	
	memcpy( part_vertsp,
			_mpntsprtp->GetDispList()->_vert_datap[0],
			sizeof(PARTICLE_VERTEX) * n );

	vbuffp->Unlock();
#endif
*/
}

//==================================================================
void RendM5D::PntSprt::BeginRenderState_s( RendDevice *rdevicep )
{
	rdevicep->_DrawState.SetAlphaTest( true, PSYSGFX::TESTFUNC_GREATEREQUAL, 0 );
	rdevicep->_DrawState.SetZWrite( false );
}

//==================================================================
void RendM5D::PntSprt::EndRenderState_s( RendDevice *rdevicep )
{
	rdevicep->_DrawState.SetZWrite( true );
}

//==================================================================
void RendM5D::PntSprt::PreRender()
{
	int		buff_idx = _cur_buff_idx;
	// needs update right from the start
	if ( _need_update[ buff_idx ] )
	{
		_need_update[ buff_idx ] = false;
		updateGeometry( buff_idx );
	}
}

//==================================================================
void RendM5D::PntSprt::Render()
{
	if ( _mpntsprtp->GetActiveVerts() <= 0 )
		return;

#ifdef TARGET_D3D
	_rdevicep->_ShaderMng.SelectPntSprtShader(	_mpntsprtp->GetDispList()->HasCol(),
												_mpntsprtp->GetMaxSize() );

	RendM5D::Material	*rmatep = (RendM5D::Material *)_mpntsprtp->GetMaterial()->_userdatap;
	rmatep->SelectMaterial();

	_rdevicep->_ShaderMng.SetParticleScale( _mpntsprtp->GetMaxSize() );


	int		buff_idx = _cur_buff_idx++;

	if ( _cur_buff_idx >= NUM_PARTICLE_BUFFERS )
		_cur_buff_idx = 0;

	_rdevicep->SelectVertexBuffer( _vbuffs[buff_idx] );
	_rdevicep->GetD3DDevice()->DrawPrimitive( D3DPT_POINTLIST, 0, _mpntsprtp->GetActiveVerts() );
#endif
}
